package gzdev;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 生成mybatis的注解类型的映射接口
 */
public class GenerateDao extends GzFile {

    // 接口类名的模板
    private final String daoName;

    private final String packageName;

    private final String pojoPackageName;

    private final GzConfig config;

    /**
     *
     * @param config
     */
    public GenerateDao(GzConfig config) {
        this.daoName = "%s" + config.getDaoSuffix() ;
        this.packageName = config.getDaoPackage();
        this.config = config;
        this.pojoPackageName = config.getPojoPackage();
    }

    // 输出dao代码到文件中
    public void outDao(String tableName, List<Map<String, Object>> tableStructure) throws IOException {
        StringBuilder content = new StringBuilder();
        appendHeader(content, tableName);
        appendBody(content, tableName, tableStructure);
        appendFooter(content);
        out(packageName, String.format(daoName, getJavaNameFromTb(tableName)) + ".java", content.toString());
    }

    private void appendFooter(StringBuilder content) {
        content.append("\n}");
    }

    /**
     * 添加方法体
     * @param content
     * @param tableName 数据库表名
     * @param tableStructure 数据库表结构
     */
    private void appendBody(StringBuilder content, String tableName, List<Map<String, Object>> tableStructure) {
        // 插入语句模板
        String addTemplate = "\n\n\t@Insert(\"insert into %s(%s) values(%s)\")\n\tInteger add(%s object);";
        // 删除语句模板
        String delTemplate = "\n\n\t@Delete(\"delete from %s where %s=#{%s}\")\n\tInteger delete(%s id);";
        // 查询语句模板
        String getTemplate = "\n\n\t@Select(\"select * from %s\")\n\tList<%s> selects();";
        // 更新模板
        String updateTemplate = "\n\n\t@Update(\"update %s set %s where %s=#{%s} \")\n\tInteger update(%s object);";
        List<String> columns = new ArrayList<>();
        List<String> columnsJavaName = new ArrayList<>();
        // 查询主键
        String idSqlName = null;
        String idType = null;
        String idJavaName = null;
        for (Map<String,Object> map : tableStructure){
            String tmpColName = (String) map.get(GzDBInfo.COLUMN_NAME);
            columns.add(tmpColName);
            columnsJavaName.add(getValNameFromColumn(tmpColName));
            if ((boolean)map.get(GzDBInfo.IS_KEY)){
                idSqlName = tmpColName;
                idType = config.getJavaType((String) map.get(GzDBInfo.TYPE));
            }
        }
        Objects.requireNonNull(idSqlName);
        idJavaName = getValNameFromColumn(idSqlName);
        Objects.requireNonNull(idType);
        String tablePojoName = getJavaNameFromTb(tableName);
        // 填充插入模板内容
        String addTemplateContent2 = String.join(",", columns);
        String addTemplateContent3 = columnsJavaName.stream().map(item -> String.format("#{%s}", item)).collect(Collectors.joining(","));
        content.append(String.format(addTemplate, tableName, addTemplateContent2, addTemplateContent3, tablePojoName));
        // 填充删除模板内容
        content.append(String.format(delTemplate, tableName, idSqlName, idJavaName, idType));
        // 填充查询语句模板
        content.append(String.format(getTemplate, tableName, tablePojoName));
        // 填充更新语句的模板
        StringBuilder updateTemplateContent2 = new StringBuilder();
        for (int i = 0; i < columns.size(); i ++){
            updateTemplateContent2.append(String.format("%s=#{%s},", columns.get(i), columnsJavaName.get(i)));
        }
        // 删除最后一个 , 号
        updateTemplateContent2.deleteCharAt(updateTemplateContent2.length() - 1);
        content.append(String.format(updateTemplate, tableName, updateTemplateContent2.toString(), idSqlName, idJavaName, tablePojoName));
    }

    private void appendHeader(StringBuilder content, String tableName) {
        String template = "package %s;\n\nimport org.apache.ibatis.annotations.*;\nimport java.util.List;\nimport %s;\n\n@Mapper\npublic interface %s {";
        String daoName = String.format(this.daoName, getJavaNameFromTb(tableName));
        content.append(String.format(template, packageName, pojoPackageName + "." + getJavaNameFromTb(tableName), daoName));
    }
}
